/*
 * uart.c
 *
 * Created: 7/7/2011 9:55:17 PM
 *  Author: Tim
 */ 
#include "uart.h"


//these functions are used for outputing data from the uarts

void comPortPut(uint8_t *packet,uint8_t packetLength)
{
	uint8_t i;
	for(i=0;i<packetLength;i++)
	{
		bufferWrite(&bufTxD1,packet[i]);
	}
	USARTD1.STATUS |= USART_TXCIF_bm;	//setting this bit should cause the txc interrupt to be triggered  
}

uint8_t comPortGet(uint8_t *packet, uint8_t packetLength)
{
	uint8_t i;
	
	uint8_t *virtualBufferHead = bufRxD1.head;	//preserve head of ring buffer
	uint8_t *virtualBufferTail = bufRxD1.tail;  //preserve tail of ring buffer
	
	for(i=0;i<packetLength;i++)
	{
		if(dataInBuf(&bufRxD1))packet[i] = bufferRead(&bufRxD1);
		else
		{
			bufRxD1.head = virtualBufferHead;
			bufRxD1.tail = virtualBufferTail;
			return 0;
		}
	}
	return 1;
}

uint8_t bufferRead(buf_t *buffer){	
	if (buffer->tail == buffer->bufferEnd){
		uint8_t temp = *buffer->tail;
		buffer->tail = buffer->bufferBegin;
		return temp;
	}
	else return *buffer->tail++;
}

void bufferWrite(buf_t *buffer, char c){
	if(buffer->head == buffer->bufferEnd){
		*buffer->head = c;
		buffer->head = buffer->bufferBegin;	
	}		
	else *buffer->head++ = c;
}

uint8_t dataInBuf(buf_t *buffer){
	if(buffer->head == buffer->tail) return 0;	//no data to be read
	else return 1;	
}

ISR(USARTD1_RXC_vect){
	cli();
	bufferWrite(&bufRxD1,USARTD1.DATA);				//when data has arrived via the usart it is immediately stored in the ring buffer
	sei();
}

ISR(USARTD1_TXC_vect)
{
	cli();
	if(dataInBuf(&bufTxD1))
	{ 
		while(!(USARTD1.STATUS & USART_DREIF_bm));	
		USARTD1.DATA = bufferRead(&bufTxD1);		//this is used to send packets of data in quick bursts
	}
	sei();
}

//initialization functions for the uarts
void comPortInit()
{
	PMIC.CTRL |= PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm;	
	
	USARTD1.CTRLA |= USART_RXCINTLVL_MED_gc;
	USARTD1.CTRLB = USART_CTRLB_115200;
	USARTD1.CTRLC = USART_CMODE_ASYNCHRONOUS_gc | USART_PMODE_DISABLED_gc | USART_CHSIZE_8BIT_gc;
	USARTD1.BAUDCTRLA = USART_BAUDCTRLA_115200;
	USARTD1.BAUDCTRLB = USART_BAUDCTRLB_115200;
}
